<template>
  <el-col :span="isTableForm ? 24 : 8" v-bind="item.colProps" v-if="isRender">
    <el-form-item :label="isTableForm ? '' : item.label"
      :prop="isTableForm ? `data.${scope!.$index}.${item.prop}` : item.prop" :rules="rules">

      <component :is="CustomComponent" v-model="itemValue"
        v-bind="{ ...attributes, ...item.props, ...itemScopeProps, ...clearScopeProps }" v-on="events">

        <!-- 仅查看模式 -->
        <span v-if="item.type === 'view'">{{ modelValue }}</span>

        <!-- 选择器模式便捷option -->
        <template v-else-if="item.type === 'select'">
          <template v-if="itemOptions && itemOptions.length && itemOptions[0].value !== undefined">
            <el-option v-for="(o, i) in itemOptions" :key="i" v-bind="o">
              <template v-for="(slot, name) in o.slots" v-slot:[name] :key="name">
                <div v-if="typeof slot === 'string'"> {{ slot }} </div>
                <div v-else-if="typeof slot.content === 'string'" v-bind="slot.props" v-on="{ ...slot.events }">
                  {{ slot.content }}
                </div>
                <component v-else-if="!slot.content" :is="slot" />
                <component v-else :is="slot.content" v-bind="slot.props" v-on="{ ...slot.events }" />
              </template>
            </el-option>
          </template>
          <template v-else-if="itemOptions && itemOptions.length && itemOptions[0].options">
            <el-option-group v-for="group in itemOptions" :key="group.label" :label="group.label"
              :disabled="group.disabled">
              <el-option v-for="(o, i) in group.options" :key="i" v-bind="o">
                <template v-for="(slot, name) in o.slots" v-slot:[name] :key="name">
                  <div v-if="typeof slot === 'string'"> {{ slot }} </div>
                  <div v-else-if="typeof slot.content === 'string'" v-bind="slot.props" v-on="{ ...slot.events }">
                    {{ slot.content }}
                  </div>
                  <component v-else-if="!slot.content" :is="slot" />
                  <component v-else :is="slot.content" v-bind="slot.props" v-on="{ ...slot.events }" />
                </template>
              </el-option>
            </el-option-group>
          </template>
        </template>

        <!-- 元素插槽 -->
        <template v-for="(slot, name) in item.slots" v-slot:[name] :key="name">
          <div v-if="typeof slot === 'string'"> {{ slot }} </div>
          <div v-else-if="typeof slot.content === 'string'" v-bind="slot.props" v-on="{ ...slot.events }">
            {{ slot.content }}
          </div>
          <component v-else-if="!slot.content" :is="slot" />
          <component v-else :is="slot.content" v-bind="slot.props" v-on="{ ...slot.events }" />
        </template>

      </component>

    </el-form-item>
  </el-col>
</template>
<script lang="ts" setup>
import { deepClone } from '@/utils/func'
import { tranElComponent } from './hooks';
import { computed, reactive } from 'vue';
import type { Component } from 'vue';
import { ElCol, ElFormItem, ElOption } from 'element-plus'


interface Props {
  modelValue: any // 元素绑定值
  item: ObjectAny // 元素
  mode: String // 表单模式
  scope?: ObjectAny // 表格式表单情况下，所在行的作用域
}

const props = withDefaults(defineProps<Props>(), {})
const emit = defineEmits(['update:modelValue'])

// 是否为表格式表单
const isTableForm = computed(() => props.mode.includes('_TableForm'))

const itemValue = computed({
  get() {
    return props.modelValue
  },
  set(value) {
    emit('update:modelValue', value)
  }
})

const CustomComponent = computed(() => {
  if (props.item.type === 'custom') return props.item.is as Component // 自定义
  return tranElComponent(props.item.type)
})


// 默认占位符字样需要设为“请选择”的类型列表
const selectTypeList = ['select', 'custom', 'cascader', 'datePicker']

// 表单元素公共属性
const attributes = reactive({
  // 元素拉伸
  style: computed(() => {
    if (props.item.type === 'switch') return { width: 'auto' }
    return { width: '100%' }
  }),
  // 占位符
  placeholder: computed(() => {
    if (attributes.disabled) return '' // 元素被禁用时，不显示占位符
    let result = selectTypeList.includes(props.item.type) ? '请选择' : '请输入'
    if (props.item.props && props.item.props.placeholder !== undefined) return props.item.props.placeholder
    else result += props.item.label
    return result
  }),
  // 是否禁用
  disabled: computed(() => {
    if (props.mode.includes('look')) return true
    return false
  }),
  // 元素默认带有一键清除内容
  clearable: true
})

// 表单元素经过行处理的属性
const itemScopeProps = reactive({} as ObjectAny)
const clearScopeProps = reactive({} as ObjectAny)
if (isTableForm.value) {
  for (const key in props.item.props) {
    if (key.startsWith('vScope_')) {
      itemScopeProps[key.replace('vScope_', '')] = computed(() => (props.item.props[key] as Function)(props.scope))
      clearScopeProps[key] = null
    }
  }
}

// select options处理
const itemOptions = computed(() => {
  if (props.item.type === 'select' && props.item.options) {
    let options = props.item.options
    if (typeof options === 'function') options = options(props.scope)
    return options
  }
  return void (0);
})

// 表单元素事件
const events = reactive({} as ObjectAny)
for (const key in props.item.events) {
  events[key] = (...args: any) => {
    props.item.events[key](...args, props.scope); // 添加scope到事件参数最后一位
  };
}

// 校验规则
const rules = computed(() => {
  if (!props.item.rules) return []
  const ComputedRules = deepClone(props.item.rules)
  ComputedRules.forEach((rule: ObjectAny) => {
    rule.trigger = rule.trigger || (selectTypeList.includes(props.item.type) ? 'change' : 'blur')
    rule.required ? (rule.message = rule.message || props.item.label + '不能为空') : '错误'
  })
  return ComputedRules
})

// 是否正常渲染
const isRender = computed(() => {
  if (Object.prototype.hasOwnProperty.call(props.item, 'render')) return props.item.render
  return true
})

defineExpose({})
</script>